/* eslint-disable no-prototype-builtins */
/* eslint-disable no-restricted-syntax */

import { customAlphabet } from 'nanoid';

import { defaultRandomLength } from 'Configs/common';

type GetVariableType = (data: unknown) => string;
export const getVariableType: GetVariableType = data => Object.prototype.toString.call(data).slice(8, -1);

type CheckVariableType = (data: unknown, target: string) => boolean;
export const checkVariableType: CheckVariableType = (data, str) => {
    const tmp = getVariableType(data);
    return tmp === str || tmp.toLowerCase() === str;
};

// export const getImageUrl = (url: string) => new URL(url, import.meta.url).href;

export const randomName = (prefix: string, randomLength: number = defaultRandomLength): string => {
    const char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    let suffix = '';
    for (let i = 0; i < randomLength; i++) {
        const position = Math.floor(Math.random() * char.length);
        suffix += char.substring(position, position + 1);
    }
    return `${prefix}-${suffix}`;
};

/** nanoid字母表 */
const nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
export const generateUuid = () => {
    return nanoid();
};

export function uniqBy<T = Record<string, unknown>>(array: T[], key: string) {
    if (!array.length || array === null) return array;

    return array.reduceRight((pre, next) => {
        const isExit = pre.some(item => item[key] === next[key]);

        if (!isExit) return pre.concat(next);
        return pre;
    }, [] as T[]);
}

export const waitTime = (time = 100) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(true);
        }, time);
    });
};

export function isObject<T>(obj: T) {
    return Object.prototype.toString.call(obj) === '[object Object]';
}
/**
 * 判断此类型是否是Array类型
 * @param {Array} arr
 */
export function isArray<T>(arr: T) {
    return Object.prototype.toString.call(arr) === '[object Array]';
}
/**
 *  深度比较两个对象是否相同
 * @param {Object} oldData
 * @param {Object} newData
 */

export function equalsObj(oldData: any, newData: string | any[]) {
    // 类型为基本类型时,如果相同,则返回true
    if (oldData === newData) return true;
    if (isObject(oldData) && isObject(newData) && Object.keys(oldData).length === Object.keys(newData).length) {
        // 类型为对象并且元素个数相同

        // 遍历所有对象中所有属性,判断元素是否相同
        for (const key in oldData) {
            if (oldData.hasOwnProperty(key)) {
                if (!equalsObj(oldData[key], newData[key]))
                    // 对象中具有不相同属性 返回false
                    return false;
            }
        }
    } else if (isArray(oldData) && isArray(oldData) && oldData.length === newData.length) {
        // 类型为数组并且数组长度相同

        for (let i = 0, { length } = oldData; i < length; i++) {
            if (!equalsObj(oldData[i], newData[i]))
                // 如果数组元素中具有不相同元素,返回false
                return false;
        }
    } else {
        // 其它类型,均返回false
        return false;
    }

    // 走到这里,说明数组或者对象中所有元素都相同,返回true
    return true;
}
